﻿using Newtonsoft.Json.Linq;
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

namespace MockNetCore
{
    /// <summary>
    /// 解析属性模版
    /// </summary>
    public class Parser
    {
        public static readonly String RE_KEY = "(.+)\\|(?:\\+(\\d+)|([\\+\\-]?\\d+-?[\\+\\-]?\\d*)?(?:\\.(\\d+-?\\d*))?)";
        public static readonly String RE_RANGE = "([\\+\\-]?\\d+)-?([\\+\\-]?\\d+)?";

        /// <summary>
        /// 属性匹配正则
        /// </summary>
        public static readonly Regex RE_KEY_MATCHER = new Regex(RE_KEY);

        /// <summary>
        /// 值范围匹配正则
        /// </summary>
        public static readonly Regex RE_RANGE_MATCHER = new Regex(RE_RANGE);

        /// <summary>
        ///
        /// </summary>
        /// <param name="name"></param>
        /// <returns></returns>
        public static Rule parseRule(string name = null)
        {
            Match matches = RE_KEY_MATCHER.Match(name);
            List<string> parameters = new List<string>();
            if (RE_KEY_MATCHER.IsMatch(name))
            {
                for (int i = 0; i < matches.Groups.Count; i++)
                {
                    if (i == 0) continue;
                    parameters.Add(matches.Groups[i].Value);
                }
            }
            bool isRange = false;
            int? min = null;
            int? max = null;
            int? count = null;
            if (parameters.Count > 0 && !String.IsNullOrEmpty(parameters[2]))
            {
                isRange = RE_RANGE_MATCHER.IsMatch(parameters[2]);
                Match matcher1 = RE_RANGE_MATCHER.Match(parameters[2]);
                if (isRange)
                {
                    min = int.Parse(matcher1.Groups[1].Value);
                    if (matcher1.Groups.Count >= 3 && !string.IsNullOrEmpty(matcher1.Groups[2].Value))
                        max = int.Parse(matcher1.Groups[2].Value);
                    count = max == null ? min : new Random().Next(min.Value, max.Value + 1);
                }
            }

            bool isDecimal = false;
            int? dmin = null;
            int? dmax = null;
            int? dcount = null;
            if (parameters.Count > 0 && !String.IsNullOrEmpty(parameters[3]))
            {
                isDecimal = RE_RANGE_MATCHER.IsMatch(parameters[3]);
                Match matcher1 = RE_RANGE_MATCHER.Match(parameters[3]);
                if (isDecimal)
                {
                    dmin = int.Parse(matcher1.Groups[1].Value);
                    if (matcher1.Groups.Count >= 3 && !string.IsNullOrEmpty(matcher1.Groups[2].Value))
                        dmax = int.Parse(matcher1.Groups[2].Value);
                    dcount = dmax == null ? dmin : new Random().Next(dmin.Value, dmax.Value + 1);
                }
            }

            return new Rule()
            {
                parameters = parameters,
                isRange = isRange,
                min = min,
                max = max,
                count = count,
                isDecimal = isDecimal,
                dmax = dmax,
                dmin = dmin,
                dcount = dcount
            };
        }

        public static Type parseType(Object template)
        {
            if (template.GetType().Equals(typeof(JValue)))
            {
                var type = ((JValue)template).Type;
                switch (type)
                {
                    case JTokenType.Object:
                        return typeof(object);

                    case JTokenType.Array:
                        return typeof(JArray);

                    case JTokenType.Integer:
                    case JTokenType.Float:
                        return typeof(int);

                    case JTokenType.String:
                        return typeof(string);

                    case JTokenType.Boolean:
                        return typeof(bool);
                }
            }
            return template.GetType();
        }
    }
}